
----------------------------------------------------------------
--- Copyright：  迷你玩-海马
--- Description：对一组share_dict名字进行检测，检测使用空间是否正常
--- 去掉了在每次使用的时候判断 share_dict 的使用空间，性能会更好
--- 之前是使用 uu report_share_free_space 函数判断，性能比较差
----------------------------------------------------------------

local assert     = assert
local require    = require
local bit        = bit
local coroutine  = coroutine
local debug      = debug
local io         = io
local pairs      = pairs
local ipairs     = ipairs
local math       = math
local os         = os
local print      = print
local pcall      = pcall
local xpcall     = xpcall
local rawget     = rawget
local rawset     = rawset
local select     = select
local string     = string
local table      = table
local tonumber   = tonumber
local tostring	 = tostring
local error      = error
local type       = type
local next       = next
local unpack     = unpack
local package    = package
local setmetatable = setmetatable
local getmetatable = getmetatable
local ngx = ngx


local loadstring = loadstring
local ngx_shared = ngx.shared;

local math_floor = math.floor


local table_insert  = table.insert
local string_format = string.format
local table_concat  = table.concat
local table_sort    = table.sort
local string_sub    = string.sub
local string_byte   = string.byte
local string_find   = string.find
local string_gsub   = string.gsub

local ngx_thread_spawn = ngx.thread.spawn
local ngx_thread_wait = ngx.thread.wait

local log           = require("modules.commhm.log")
local uu            = require("modules.commhm.utils")
local CNgxTimerWrap = require("modules.commhm.ngxTimerWrap" )


local FOO = {
	_VERSION   = '0.12.1',
	work_id  =  ngx.worker.id(),

	exist_shared_dict_ = {},

	status = 0,   --运行状态
};


-- 检查单个share dict的使用量
function FOO.check_share_dict_free_space( dict_name_, where_ )
	local share_ = ngx_shared[ dict_name_ ]
	if  share_ then
		local f1_ = share_:free_space()
		local c1_ = share_:capacity()
		local rate_ = f1_/c1_
		if  rate_ > 0.7 then
			-- 空间充足
			local r_ = string.format("%.4f", rate_ );
			log.day_list_simple( "dict_free", "timer",       FOO.work_id, r_, c1_/(1024*1024), where_, dict_name_)
		elseif rate_ < 0.2 then
			-- 空间告警
			local r_ = string.format("%.4f", rate_ );
			log.day_list_simple( "dict_free", "timer_error", FOO.work_id, r_, c1_/(1024*1024), where_, dict_name_)
			log.error( "shared_free_space rate=" .. r_ .. " for " .. dict_name_ )
		else
			-- 正常使用
			local r_ = string.format("%.4f", rate_ );
			log.day_list_simple( "dict_free", "timer",       FOO.work_id, r_, c1_/(1024*1024), where_, dict_name_)
		end
	end
end



---开启检测定时任务
--- name_list_ 需要检查的shared_dict名字列表
--- time_      检查时间间隔 一般600秒
--- where_     服务名字
function FOO.start_check_by_timer( name_list_, time_, where_ )

	--[[
	if  FOO.work_id > 0 then
		log.day_list_simple( "dict_free", "==start_check_by_timer", FOO.work_id, "ignore_work_id", #name_list_, where_)
		return
	else
		log.day_list_simple( "dict_free", "==start_check_by_timer", FOO.work_id, "start_work_id",  #name_list_, where_)
	end
	--]]

	--- 唯一worker调用
	local worker_only_key_ = 'shared_dict_call_' .. where_
	local t_ = uu.get_server_cache_table( 3, worker_only_key_ )
	if  t_ and t_.work_id then
		if  t_.work_id >= ngx.worker.count() then
			--worker过大， 一般是配置上减少了worker数
			log.day_list_simple( "dict_free", "==error_work_id", t_.work_id, FOO.work_id,  #name_list_, where_)
		elseif  t_.work_id ~= FOO.work_id then
			-- 其他worker占据
			log.day_list_simple( "dict_free", "==start_check_by_timer", FOO.work_id, "ignore_work_id", #name_list_, where_)
			return
		end
	end

	--需要开始打印
	uu.set_server_cache_table( 3, worker_only_key_, { t=uu.now(), work_id=FOO.work_id }, time_*2 )
	log.day_list_simple( "dict_free", "==start_check_by_timer", FOO.work_id, "start_work_id",  #name_list_, where_)


	local cc_ = 0
	--- 检查哪些dict存在 (排重)
	for i=1, #name_list_ do
		if  type(name_list_[i]) == 'string' then
			if  ngx_shared[ name_list_[i] ] then
				if  not FOO.exist_shared_dict_[ name_list_[i] ] then
					FOO.exist_shared_dict_[ name_list_[i] ] = where_
					cc_ = cc_ + 1
					log.day_list_simple( "dict_free", "==add_name", FOO.work_id, name_list_[i], where_)
				else
					log.day_list_simple( "dict_free", "==exist_name", FOO.work_id, name_list_[i], where_)
				end
			else
				log.day_list_simple( "dict_free", "==ignore_name", FOO.work_id, name_list_[i], where_)
			end
		end
	end


	if  FOO.status == 0 then
		if  cc_ > 0 then
			local function timer_func_()
				for name_, where_ in pairs( FOO.exist_shared_dict_ ) do
					FOO.check_share_dict_free_space(name_, where_ )
					uu.set_server_cache_table( 3, worker_only_key_, { t=uu.now(), work_id=FOO.work_id }, time_*2 )
				end
			end

			FOO.status = 1   ---防止重复启动
			FOO.timer_every( time_ + FOO.work_id, timer_func_ )
		end
	end

end



---定期执行一个任务
function FOO.timer_every( delay_, func_, params_ )
	local timer_ = CNgxTimerWrap:new()
	return timer_:ngx_timer_every( delay_, func_, params_  )
end

return FOO;


